package com.salton123.soulove.biz_bmob.helper

import android.content.Context
import android.provider.Settings
import android.text.TextUtils
import cn.bmob.v3.Bmob
import cn.bmob.v3.BmobBatch
import cn.bmob.v3.BmobObject
import cn.bmob.v3.BmobQuery
import cn.bmob.v3.BmobUser
import cn.bmob.v3.datatype.BatchResult
import cn.bmob.v3.datatype.BmobFile
import cn.bmob.v3.exception.BmobException
import cn.bmob.v3.listener.FindListener
import cn.bmob.v3.listener.QueryListListener
import cn.bmob.v3.listener.SaveListener
import cn.bmob.v3.listener.UploadBatchListener
import cn.bmob.v3.listener.UploadFileListener
import com.salton123.app.BaseApplication
import com.salton123.log.XLog
import com.salton123.soulove.app.BuildConfig
import com.salton123.soulove.biz_bmob.model.AndroidId
import com.salton123.soulove.biz_bmob.model.FeedbackEntity
import com.salton123.soulove.biz_bmob.model.User
import com.salton123.soulove.common.Constants
import com.salton123.soulove.common.event.CodeEvent
import com.salton123.util.EventUtil
import com.salton123.util.PreferencesUtils
import io.reactivex.Observable
import java.io.File

/**
 * User: newSalton@outlook.com
 * Date: 2019/6/3 10:52
 * ModifyTime: 10:52
 * Description:
 */
object BmobHelper {
    private val TAG = "BmobHelper"
    fun init(context: Context?) {
        Bmob.initialize(context, BuildConfig.BMOB_KEY)
        autoLogin()
        XLog.i(TAG, "init")
    }

    /**
     * 上传文件
     */
    fun uploadFile(fileLocalPath: String, callback: (progress: Int, ret: BmobFile?, err: Throwable?) -> Unit) {
        val localFile = File(fileLocalPath)
        val bmobFile = BmobFile(localFile)
        bmobFile.upload(object : UploadFileListener() {
            override fun onProgress(value: Int) {
                callback.invoke(value, null, null)
            }

            override fun done(e: BmobException?) {
                if (e == null) {
                    callback.invoke(100, bmobFile, null)
                } else {
                    callback.invoke(-1, null, e)
                }
            }
        })
    }

    fun register(
        username: String?, password: String?, email: String?
    ): Observable<User> {
        return Observable.create { emitter ->
            val user = User()
            user.username = username
            user.setPassword(password)
            user.email = email
            user.signUp(object : SaveListener<User>() {
                override fun done(user: User, e: BmobException?) {
                    if (e == null) {
                        emitter.onNext(user)
                        PreferencesUtils
                            .putString("username", username)
                        PreferencesUtils
                            .putString("password", password)
                        EventUtil.sendEvent(CodeEvent(Constants.Common.REGISTER_SUCCESS))
                    } else {
                        emitter.onError(e)
                        EventUtil.sendEvent(CodeEvent(Constants.Common.REGISTER_FAIL))
                    }
                }
            })
        }
    }

    fun register(
        username: String?, password: String?
    ): Observable<User> {
        return register(username, "", password)
    }

    fun autoLogin(): Observable<User> {
        val username = PreferencesUtils.getString("username")
        val password = PreferencesUtils.getString("password")
        return login(username, password)
    }

    fun login(
        username: String?, password: String?
    ): Observable<User> {
        return Observable.create<User> { emitter ->
            val user = User()
            user.username = username
            user.setPassword(password)
            user.login(object : SaveListener<User>() {
                override fun done(user: User, e: BmobException?) {
                    if (e == null) {
                        emitter.onNext(user)
                        PreferencesUtils
                            .putString("username", username)
                        PreferencesUtils
                            .putString("password", password)
                        EventUtil.sendEvent(CodeEvent(Constants.Common.LOGIN_SUCCESS))
                    } else {
                        EventUtil.sendEvent(CodeEvent(Constants.Common.LOGIN_FAIL))
                        emitter.onError(e)
                    }
                }
            })
        }
    }

    fun uploadBatch(
        localFileList: List<String>,
        listener: UploadBatchListener?
    ): Observable<List<BmobFile>> {
        return Observable.create<List<BmobFile>> { emitter ->
            BmobFile.uploadBatch(localFileList.toTypedArray(),
                object : UploadBatchListener {
                    override fun onSuccess(
                        list: List<BmobFile>, list1: List<String>
                    ) {
                        listener?.onSuccess(list, list1)
                        for (item: BmobFile in list) {
                            if (item.localFile.exists()) {
                                item.localFile.delete()
                            }
                        }
                        if (list1.size == localFileList.size) {
                            emitter.onNext(list)
                        }
                    }

                    override fun onProgress(i: Int, i1: Int, i2: Int, i3: Int) {
                        listener?.onProgress(i, i1, i2, i3)
                        XLog.i(
                            BmobHelper::class.java,
                            "i:$i,i1:$i1,i2:$i2,i3:$i3"
                        )
                    }

                    override fun onError(i: Int, s: String) {
                        listener?.onError(i, s)
                        XLog.i(BmobHelper::class.java, "i:$i,s:$s")
                    }
                })
        }
    }

    fun insertBatch(files: List<BmobObject?>?): Observable<Boolean> {
        return Observable.create<Boolean> { emitter ->
            BmobBatch().insertBatch(files).doBatch(object : QueryListListener<BatchResult>() {
                override fun done(
                    list: List<BatchResult>, e: BmobException?
                ) {
                    if (e != null) {
                        XLog.i(BmobHelper::class.java, "e:$e")
                    }
                    for (item: BatchResult in list) {
                        emitter.onNext(item.isSuccess)
                    }
                }
            })
        }
    }

    val loginUserId: String
        get() {
            return if (BmobUser.isLogin()) {
                BmobUser.getCurrentUser(BmobUser::class.java).objectId
            } else {
                ""
            }
        }

    fun getLoginUser(): User? {
        return BmobUser.getCurrentUser(User::class.java)
    }

    fun <T : BmobObject?> getCloudApkList(
        pageSize: Int, page: Int,
        listener: FindListener<T>?
    ) {
        val query = BmobQuery<T>()
        query.setLimit(pageSize)
        query.setSkip(page * pageSize)
        // query.addWhereEqualTo("channel", com.salton123.corelite.BuildConfig.CHANNEL);
        query.findObjects(listener)
    }

//    fun chengVersionUpdate(): Observable<AppVersion> {
//        val query = BmobQuery<AppVersion>()
//        query.setLimit(1)
//        query.setSkip(0)
//        query.addWhereGreaterThan("version_i",
//            AppUtils.getVersionCode(getInstance()))
//        query.findObjects(object : FindListener<AppVersion?>() {
//            override fun done(
//                list: List<AppVersion?>?, e: BmobException?
//            ) {
//                if ((e == null) && (list != null) && (list.isNotEmpty())) {
//                    val appVersion = list[0]
//                    emitter.onNext((appVersion)!!)
//                    emitter.onComplete()
//                }
//            }
//        })
//    }

    fun feedback(content: String?) {
        if (!TextUtils.isEmpty(content)) {
            val entity = FeedbackEntity()
            entity.ownerId = loginUserId
            entity.content = content
            entity.save(object : SaveListener<String>() {
                override fun done(s: String, e: BmobException) {}
            })
        }
    }

    fun active(id: String?) {
        val query: BmobQuery<AndroidId?> = BmobQuery()
        query.addWhereEqualTo("androidId", id)
        query.findObjects(object : FindListener<AndroidId?>() {
            override fun done(list: MutableList<AndroidId?>?, p1: BmobException?) {
                if (list == null || list.isEmpty()) {
                    val androidId = AndroidId(id)
                    androidId.save(object : SaveListener<String>() {
                        override fun done(s: String?, e: BmobException) {
                            XLog.i(TAG, "active success:$e")
                        }
                    })
                }
            }
        })
    }

    fun active() {
        val androidID = Settings.Secure.getString(
            BaseApplication.sInstance.contentResolver, Settings.Secure.ANDROID_ID
        )
        XLog.i(TAG, "androidID:$androidID")
        active(androidID)
    }

    fun logout() {
        BmobUser.logOut()
    }
}